#include "Bit_map.hxx"

namespace fuh
{
    struct BKDRHash
    {
        size_t operator()(const string& s)
        {
        // BKDR
        size_t value = 0;
        for (auto ch : s)
        {
            value *= 31;
            value += ch;
        }
            return value;
        }
    };
    struct APHash
    {
        size_t operator()(const string& s)
        {
            size_t hash = 0;
            for (long i = 0; i < s.size(); i++)
            {
                if ((i & 1) == 0)
                {
                hash ^= ((hash << 7) ^ s[i] ^ (hash >> 3));
                }
                else
                {
                    hash ^= (~((hash << 11) ^ s[i] ^ (hash >> 5)));
                }
            }
            return hash;
        }
    };
    
    struct DJBHash
    {
        size_t operator()(const string& s)
        {
            size_t hash = 5381;
            for (auto ch : s)
            {
                hash += (hash << 5) + ch;
            }
            return hash;
        }
    };
    template<size_t N  =100,
    size_t X = 5,
    class K = string,
    class HashFunc1 = BKDRHash,
    class HashFunc2 = APHash,
    class HashFunc3 = DJBHash>
    class Bloomfilter{
        Bit_map _bs;
        HashFunc1 hash1;
        HashFunc2 hash2;
        HashFunc3 hash3;
        public:
        Bloomfilter()
        :_bs(N*X)
        {

        }
        bool Set(const K& key)
        {
            size_t len = X*N;
            size_t i1 = hash1(key)%len;
            size_t i2 = hash2(key)%len;
            size_t i3 = hash3(key)%len;
            _bs.set(i1);
            _bs.set(i2);
            _bs.set(i3);
            return 1;
        }
        bool test(const K&key)
        {
            size_t len = X*N;
            size_t index1 = HashFunc1()(key) % len;
            if (_bs.isExisted(index1) == false)
            return false;
            size_t index2 = HashFunc2()(key) % len;
            if (_bs.isExisted(index2) == false)
            return false;
            size_t index3 = HashFunc3()(key) % len;
            if (_bs.isExisted(index3) == false)
            return false;
            return true;  // 存在误判的
        }
};  
};